/////precompiled////////
#include "precompiled.h"
////////////////////////


#include "svl_TStream.h"
using namespace svl;
                      
// TStream_ObjectVer ///////////////////////////////////////////////////////////

//
TStream_ObjectVer::TStream_ObjectVer()
{
  prevVersion = NULL;
  nextVersion = NULL;
  numVersion  = 0;
}

//
void TStream_ObjectVer::SetPrevVersion(TStream_ObjectVer &PrevVersion)
{
  prevVersion             = &PrevVersion;
  PrevVersion.nextVersion =  this;
  numVersion              =  PrevVersion.numVersion + 1;
}

//
void TStream_ObjectVer::PrevVersionIsRead()
{
  Except("PrevVersionIsRead");
}

// TStream /////////////////////////////////////////////////////////////////////

//
TStream &TStream::operator << (TStream_Object &Object)
{
  Object.WriteTo(*this); return *this;
}

//
TStream &TStream::operator >> (TStream_Object &Object)
{
  Object.ReadFrom(*this); return *this;
}

//
TStream &TStream::operator << (const TStream_ObjectVer &Object_)
{
  TStream_ObjectVer &Object = (TStream_ObjectVer&)Object_;

  WriteNumVersion(Object.numVersion);
  Object.WriteTo(*this);
  return *this;
}

//
TStream &TStream::operator >> (const TStream_ObjectVer &Object_)
{
  TStream_ObjectVer &Object = (TStream_ObjectVer&)Object_;

  if (Object.nextVersion != NULL)
  {
    Except
    (
      "operator >> (TStream_ObjectVer &Object)"
    );
    return *this;
  }

  int NumVersion; ReadNumVersion(NumVersion);

  TStream_ObjectVer *ReadVersion = GetVersion(&Object,NumVersion);

  if (!ReadVersion) { return *this;}

  ReadVersion->ReadFrom(*this);

  TStream_ObjectVer *NextVersion = ReadVersion->nextVersion;

  while (NextVersion)
  {
    NextVersion->PrevVersionIsRead();
    NextVersion = NextVersion->nextVersion;
  }
  return *this;
}

//
void TStream::WriteNumVersion(int /*NumVersion*/)
{
  Except("WriteNumVersion");
}

//
void TStream::ReadNumVersion(int &/*NumVersion*/)
{
  Except("ReadNumVersion");
}

//
TStream_ObjectVer *TStream::GetVersion
(
  TStream_ObjectVer *LastVersion,
  int                NumVersion
)
{
  TStream_ObjectVer *Version = LastVersion; while (Version)
  {
    if (Version->numVersion == NumVersion)
    {
      return Version;
    }
    Version = Version->prevVersion;
  }
  Except("GetVersion[1]"); return NULL;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

// TStreamMem //////////////////////////////////////////////////////////////////

//
TStreamMem &TStreamMem::operator = (TStreamMem &V)
{
  *(TMem*)this = (TMem&)V; offsRead = V.offsRead; return *this;
}

//
TStreamMem &TStreamMem::operator = (TMem &V)
{
  *(TMem*)this = V; offsRead = 0; return *this;
}
/*
//
TStream &TStreamMem::operator << (bool V)
{
  TMem::Add((BYTE*)&V,sizeof(V)); return *this;
}

//
TStream &TStreamMem::operator >> (bool &V)
{
  V = 0; if ((int)(offsRead + sizeof(V)) > TMem::Size())
  {
    TStream::Except("operator >> (bool &V)",true);
  }
  else { V = *(bool*)(TMem::Ptr() + offsRead);}

  offsRead += sizeof(V); return *this;
}
*/
//
TStream &TStreamMem::operator << (__int32 V)
{
  TMem::Add((BYTE*)&V,sizeof(V)); return *this;
}

//
TStream &TStreamMem::operator >> (__int32 &V)
{
  V = 0; if ((int)(offsRead + sizeof(V)) > TMem::Size())
  {
    TStream::Except("operator >> (__int32 &V)");
  }
  else { V = *(__int32*)(TMem::Ptr() + offsRead);}

  offsRead += sizeof(V); return *this;
}

//
TStream &TStreamMem::operator << (__int8 V)
{
  TMem::Add((BYTE*)&V,sizeof(V)); return *this;
}

//
TStream &TStreamMem::operator >> (__int8 &V)
{
  V = 0; if ((int)(offsRead + sizeof(V)) > TMem::Size())
  {
    TStream::Except("operator >> (__int8 &V)");
  }
  else { V = *(__int8*)(TMem::Ptr() + offsRead);}

  offsRead += sizeof(V); return *this;
}

//
TStream &TStreamMem::operator << (WORD V)
{
  TMem::Add((BYTE*)&V,sizeof(V)); return *this;
}

//
TStream &TStreamMem::operator >> (WORD &V)
{
  V = 0; if ((int)(offsRead + sizeof(V)) > TMem::Size())
  {
    TStream::Except("operator >> (WORD &V)");
  }
  else { V = *(WORD*)(TMem::Ptr() + offsRead);}

  offsRead += sizeof(V); return *this;
}

//
TStream &TStreamMem::operator << (char *V)
{
  TString S(V); *this << S; return *this;
}

//
TStream &TStreamMem::operator << (TString &V)
{
 *this << (int)V.Len(); if (V.Len())
  {
    TMem::Add((BYTE*)V.S(),V.Len());
  }
  return *this;
}

//
TStream &TStreamMem::operator >> (TString &V)
{
  int Len; *this >> Len; V.Clr(); if (Len && Len < 65530L)
  {
    if (offsRead + Len > TMem::Size())
    {
      TStream::Except("operator >> (TString &V)");
    }
    else { V.Add((char*)(TMem::Ptr() + offsRead),Len);}
  }
  offsRead += Len; return *this;
}

//
/*
TStream &TStreamMem::operator << (System::String &V)
{
  *this << V.c_str(); return *this;
}

//
TStream &TStreamMem::operator >> (System::String &V)
{
  TString S; *this >> S; V = S.S(); return *this;
}
*/

//
TStream &TStreamMem::operator << (TMem &V)
{
 *this << (int)V.Size(); if (V.Size())
  {
    TMem::Add(V.Ptr(),V.Size());
  }
  return *this;
}

//
TStream &TStreamMem::operator >> (TMem &V)
{
  int Size; *this >> Size; V.Clear(); if (Size && Size < 65530L)
  {
    if (offsRead + Size > TMem::Size())
    {
      TStream::Except("operator >> (TMem &V)");
    }
    else { V.Add(TMem::Ptr() + offsRead,(int)Size);}
  }
  offsRead += Size; return *this;
}

//
TStream &TStreamMem::operator << (TStreamMem &V)
{
 *this << (TMem&)V; return *this;
}

//
TStream &TStreamMem::operator >> (TStreamMem &V)
{
 *this >> (TMem&)V; return *this;
}

//
TStream &TStreamMem::operator << (const TStream_ObjectVer &Object)
{
  *(TStream*)this << Object; return *this;
}

//
TStream &TStreamMem::operator >> (const TStream_ObjectVer &Object)
{
  *(TStream*)this >> Object; return *this;
}
